home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / news / readers / skim-0.8 / skim-0 / skim-0.8.4 / VarBuf.c < prev    next >
C/C++ Source or Header  |  1996-02-18  |  13KB  |  552 lines

  1. /*
  2.  * NAME
  3.  *   VarBuf.c
  4.  * DESCRIPTION
  5.  *   VarBuf is An Abstract Data Type which provides variable size memory 
  6.  *   buffers. A VarBuf grows and shrinks in size automatically. The caller does
  7.  *   not have to take care of memory allocation. Operations and queries are 
  8.  *   available to use a VarBuf to store a variable size character string.
  9.  * COPYRIGHT
  10.  *   VarBuf - Variable size buffer ADT.
  11.  *   Copyright (C) 1996  Rene W.J. Pijlman
  12.  *
  13.  *   This program is free software; you can redistribute it and/or modify
  14.  *   it under the terms of the GNU General Public License as published by
  15.  *   the Free Software Foundation; either version 2 of the License, or
  16.  *   (at your option) any later version.
  17.  *
  18.  *   This program is distributed in the hope that it will be useful,
  19.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  *   GNU General Public License for more details.
  22.  *
  23.  *   You should have received a copy of the GNU General Public License
  24.  *   along with this program; if not, write to the Free Software
  25.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  * VERSION
  27.  *   $Header: /home/rene/sys/CVS_MasterSourceRepository/skim/VarBuf.c,v 1.8 1996/02/16 23:10:55 rene Exp $
  28.  *   Distributed with Skim version 0.8.4.
  29.  */
  30.  
  31. #include "Types.h"
  32. #include "VarBuf.h"
  33.  
  34. #include <stdio.h>
  35. #include <assert.h>
  36. #include <stdlib.h>
  37. #include <stdarg.h>
  38. #include <string.h>
  39. #include <errno.h>
  40. #include <ctype.h>
  41.  
  42. #include "MemAlloc.h"
  43. #include "StandardIO.h"
  44.  
  45. #define  CLASS_NAME "VarBuf"
  46. #include "CheckForDebris.h"
  47.  
  48. /* The private attributes of a VarBuf. */
  49. struct _VarBuf {
  50.     size_t Size;
  51.     void * Address;
  52. };
  53.  
  54. #define VB_EXPAND_SIZE_FOR_LINE     80
  55. #define VB_EXPAND_SIZE_FOR_FILE   4096
  56.  
  57.  
  58. VarBuf VBCreate( void )
  59. {
  60.     VarBuf Result;
  61.  
  62.     Result = MemAlloc( sizeof( struct _VarBuf ) );
  63.  
  64.     Result->Address = NULL;
  65.     Result->Size = 0;
  66.  
  67.     IncrementObjectCount();
  68.  
  69.     assert( VBIsOK(Result) );
  70.  
  71.     return Result;
  72. }
  73.  
  74.  
  75. Boolean VBIsOK( VarBuf This )
  76. {
  77.     return This != NULL &&
  78.            ( (This->Size == 0) == (This->Address == NULL) );
  79. }
  80.  
  81.  
  82. VarBuf VBClone( VarBuf This )
  83. {
  84.     VarBuf Result = VBCreate();
  85.  
  86.     Result->Size = This->Size;
  87.     Result->Address = MemAlloc( This->Size );
  88.  
  89.     memmove( Result->Address, This->Address, This->Size );
  90.  
  91.     return Result;
  92. }
  93.  
  94.  
  95. void VBAppendString( VarBuf This, const char * String )
  96. {
  97.     size_t StringLength;
  98.     size_t NewSize;
  99.  
  100.     assert( This != NULL && String != NULL );
  101.  
  102.     StringLength = strlen( String );
  103.     NewSize = This->Size + StringLength;
  104.  
  105.     if ( NewSize > 0 )
  106.     {
  107.         This->Address = MemRealloc( This->Address, NewSize );
  108.     memcpy( This->Address + This->Size, String, StringLength );
  109.     }
  110.  
  111.     This->Size = NewSize;
  112. }
  113.  
  114.  
  115. void VBAppendCharacter( VarBuf This, char c )
  116. {
  117.     char String[2];
  118.  
  119.     assert( This != NULL );
  120.  
  121.     String[0] = c;
  122.     String[1] = '\0';
  123.  
  124.     VBAppendString( This, String );
  125. }
  126.  
  127.  
  128. void VBAppendVB( VarBuf This, VarBuf Source )
  129. {
  130.     size_t NewSize;
  131.  
  132.     assert( This != NULL && Source != NULL );
  133.  
  134.     NewSize = This->Size + Source->Size;
  135.  
  136.     if ( NewSize > 0 )
  137.     {
  138.     This->Address = MemRealloc( This->Address, NewSize );
  139.         memcpy( This->Address + This->Size, Source->Address, Source->Size );
  140.     }
  141.  
  142.     This->Size = NewSize;
  143. }
  144.  
  145.  
  146. void VBDestroy( VarBuf This )
  147. {
  148.     if ( This != NULL )
  149.     {
  150.     MemFree( This->Address );
  151.     MemFree( This );
  152.  
  153.     DecrementObjectCount();
  154.     }
  155. }
  156.  
  157. void VBReadFile( VarBuf This, StandardIO IO )
  158. {
  159.     assert( This != NULL );
  160.     assert( IO != NULL );
  161.     assert( SIOIsOpenForRead(IO) );
  162.  
  163.     while ( !SIOEndOfFile(IO) )
  164.     {
  165.         This->Address = MemRealloc( This->Address,
  166.                                     This->Size + VB_EXPAND_SIZE_FOR_FILE );
  167.     This->Size += SIORead( IO, This->Address + This->Size,
  168.                            VB_EXPAND_SIZE_FOR_FILE );
  169.     }
  170.  
  171.     This->Address = MemRealloc( This->Address, This->Size );
  172. }
  173.  
  174. void VBWriteFile( VarBuf This, StandardIO IO )
  175. {
  176.     assert( This != NULL );
  177.     assert( IO != NULL );
  178.     assert( SIOIsOpenForWrite(IO) );
  179.  
  180.     SIOWrite( IO, This->Address, This->Size );
  181. }
  182.  
  183.  
  184. /* Append one line from File and append to the VarBuf. */
  185. Boolean VBReadLine( VarBuf This, StandardIO IO, Boolean IncludeLinefeed )
  186. {
  187.     Boolean ReadSomeData = False;
  188.     Boolean MoreData = True;
  189.     size_t OldSize;
  190.  
  191.     assert( This != NULL && IO != NULL );
  192.  
  193.     OldSize = This->Size;
  194.  
  195.     while ( MoreData )
  196.     {
  197.         This->Address = MemRealloc( This->Address,
  198.                                     This->Size + VB_EXPAND_SIZE_FOR_LINE );
  199.  
  200.     SIOFileGetPartOfLine( IO, (char *)This->Address + This->Size,
  201.                           VB_EXPAND_SIZE_FOR_LINE );
  202.     if ( SIOEndOfFile(IO) )
  203.     {
  204.         MoreData = False;
  205.     }
  206.     else
  207.     {
  208.         ReadSomeData = True;
  209.         This->Size += strlen( (char *)(This->Address + This->Size) );
  210.         MoreData = ((char *)This->Address)[ This->Size - 1] != '\n';
  211.     }
  212.     }
  213.  
  214.     if( ReadSomeData )
  215.     {
  216.     if ( !IncludeLinefeed && 
  217.          ((char *)This->Address)[ This->Size - 1] == '\n' )
  218.     {
  219.         This->Address = MemRealloc( This->Address, This->Size - 1 );
  220.         This->Size--;
  221.     }
  222.     }
  223.     else
  224.     {
  225.         /* Back to original size. */
  226.         This->Address = MemRealloc( This->Address, OldSize );
  227.     }
  228.  
  229.     return ReadSomeData;
  230. }
  231.  
  232.  
  233. void * VBAddress( VarBuf This )
  234. {
  235.     assert( This );
  236.  
  237.     return This->Address;
  238. }
  239.  
  240. size_t VBSize( VarBuf This )
  241. {
  242.     assert( This != NULL );
  243.  
  244.     return This->Size;
  245. }
  246.  
  247.  
  248. void VBReset( VarBuf This )
  249. {
  250.     This->Address = MemRealloc( This->Address, 0 );
  251.     This->Size = 0;
  252. }
  253.  
  254.  
  255. /* This suffices for 32 and 64 bit architectures. */
  256. #define MAXLEN_INTEGRAL_AS_STRING 20
  257.  
  258.  
  259. /*
  260.  * The following subset of printf() conversion specifications is supported:
  261.  *
  262.  *     %s    :  char *; print the null terminated string. Precision is not 
  263.  *              supported.
  264.  *     %c    :  char; print one character.
  265.  *     %d    :  integer.
  266.  *     %u    :  unsigned integer.
  267.  *     %ld   :  long.
  268.  *     %lu   :  unsigned long.
  269.  *     %%    :  Append one '%'.
  270.  *
  271.  * And the following extensions to the printf() conversion specifications are
  272.  * supported:
  273.  *     %V    :  VarBuf. Print the contents of the VarBuf.
  274.  */
  275. void VBPrintfVA( 
  276.     VarBuf This, 
  277.     const char * FormatString, 
  278.     va_list ArgumentPointer )
  279. {
  280.     const char * p;
  281.     char NumberBuffer[ MAXLEN_INTEGRAL_AS_STRING + 1 ];
  282.  
  283.     for ( p = FormatString; *p != '\0'; p++ )
  284.     {
  285.         if ( *p == '%' )
  286.         {
  287.             switch( *++p )
  288.             {
  289.                 case 's':
  290.                     VBAppendString( This, va_arg( ArgumentPointer, char * ) );
  291.                     break;
  292.  
  293.         case 'c':
  294.             VBAppendCharacter( This, va_arg( ArgumentPointer, char ) );
  295.             break;
  296.  
  297.         case 'V':
  298.                     VBAppendVB( This, va_arg( ArgumentPointer, VarBuf ) );
  299.                     break;
  300.  
  301.         case 'd':
  302.             sprintf( NumberBuffer, "%d",
  303.                      va_arg( ArgumentPointer, int ) );
  304.             VBAppendString( This, NumberBuffer );
  305.             break;
  306.  
  307.         case 'u':
  308.             sprintf( NumberBuffer, "%u", 
  309.                      va_arg( ArgumentPointer, unsigned int ) );
  310.             VBAppendString( This, NumberBuffer );
  311.             break;
  312.  
  313.         case 'l':
  314.                     switch( *++p )
  315.                     {
  316.                         case 'd':
  317.                 sprintf( NumberBuffer, "%ld",
  318.                      va_arg( ArgumentPointer, long ) );
  319.                 VBAppendString( This, NumberBuffer );
  320.                             break;
  321.  
  322.                         case 'u':
  323.                 sprintf( NumberBuffer, "%lu", 
  324.                      va_arg( ArgumentPointer, unsigned long ) );
  325.                 VBAppendString( This, NumberBuffer );
  326.                             break;
  327.  
  328.             default:
  329.                 SIOPrintf( StandardError,
  330.                    "Unknown conversion specification: %%l%c\n",
  331.                    *p );
  332.                 exit( EXIT_FAILURE );
  333.                 break;
  334.                     }
  335.                     break;
  336.  
  337.         case '%':
  338.                     VBAppendCharacter( This, '%' );
  339.                     break;
  340.  
  341.         default:
  342.                     SIOPrintf( StandardError,
  343.                "Unknown conversion specification: %%%c\n",
  344.                            *p );
  345.             exit( EXIT_FAILURE );
  346.             break;
  347.             }
  348.         }
  349.         else
  350.         {
  351.             VBAppendCharacter( This, *p );
  352.         }
  353.     }
  354.  
  355. }
  356.  
  357.  
  358. void VBPrintf( VarBuf This, const char * FormatString, ...)
  359. {
  360.     va_list ArgumentPointer;
  361.  
  362.     va_start( ArgumentPointer, FormatString );
  363.  
  364.     VBPrintfVA( This, FormatString, ArgumentPointer );
  365.  
  366.     va_end( ArgumenPointer );
  367. }
  368.  
  369.  
  370. char * VBAsString( VarBuf This )
  371. {
  372.     /* Make null-terminated, but the '\0' is not part of the VarBuf. */
  373.     This->Address = MemRealloc( This->Address, This->Size + 1 );
  374.     ((char *)This->Address)[This->Size] = '\0';
  375.  
  376.     return This->Address;
  377. }
  378.  
  379.  
  380. void VBShiftLeft( VarBuf This, size_t Distance )
  381. {
  382.     assert( This->Size >= Distance );
  383.  
  384.     memmove( This->Address, This->Address + Distance, This->Size - Distance );
  385.     This->Address = MemRealloc( This->Address, This->Size - Distance );
  386.     This->Size = This->Size - Distance;
  387. }
  388.  
  389.  
  390. void VBShiftRight( VarBuf This, size_t Distance, char Pad )
  391. {
  392.     This->Address = MemRealloc( This->Address, This->Size + Distance );
  393.     memmove( This->Address + Distance, This->Address, This->Size );
  394.     This->Size = This->Size + Distance;
  395.     memset( This->Address, (int)Pad, Distance );
  396. }
  397.  
  398.  
  399. void VBTruncate( VarBuf This, size_t NewSize )
  400. {
  401.     assert( NewSize <= This->Size );
  402.  
  403.     This->Address = MemRealloc( This->Address, NewSize );
  404.     This->Size = NewSize;
  405. }
  406.  
  407.  
  408. /* Make the buffer fixed size, by truncating or by appending characters. */
  409. void VBFixSize( VarBuf This, size_t NewSize, char PadCharacter )
  410. {
  411.     if ( This->Size < NewSize )
  412.     {
  413.     This->Address = MemRealloc( This->Address, NewSize );
  414.  
  415.     while ( This->Size < NewSize )
  416.     {
  417.         ((char *)This->Address)[This->Size++] = PadCharacter;
  418.     }
  419.     }
  420.     else if ( This->Size > NewSize )
  421.     {
  422.     VBTruncate( This, NewSize );
  423.     }
  424. }
  425.  
  426.  
  427. void VBRemoveLeadingBlanks( VarBuf This )
  428. {
  429.     size_t NumberOfLeadingBlanks;
  430.     char * p;
  431.  
  432.     for ( NumberOfLeadingBlanks = 0, p = ((char *)This->Address);
  433.           NumberOfLeadingBlanks < This->Size && isspace( *p );
  434.           p++ )
  435.     {
  436.         NumberOfLeadingBlanks++;
  437.     }
  438.  
  439.     VBShiftLeft( This, NumberOfLeadingBlanks );
  440. }
  441.  
  442.  
  443. void VBRemoveTrailingBlanks( VarBuf This )
  444. {
  445.     size_t NewSize;
  446.     char * p;
  447.  
  448.     for ( NewSize = This->Size, p = ((char *)This->Address) + This->Size - 1;
  449.           NewSize > 0 && isspace( *p );
  450.           p-- )
  451.     {
  452.         NewSize--;
  453.     }
  454.  
  455.     This->Address = MemRealloc( This->Address, NewSize );
  456.     This->Size = NewSize;
  457. }
  458.  
  459. void VBSplitAtOffset( 
  460.     VarBuf This, 
  461.     size_t Offset, 
  462.     VarBuf Part1,
  463.     VarBuf Part2 )
  464. {
  465.     assert( This != NULL && Part1 != NULL && Part2 != NULL );
  466.     assert( Part1->Size == 0 && Part2->Size == 0 );
  467.     assert( This->Size >= Offset );
  468.  
  469.     Part1->Address = MemRealloc( Part1->Address, Offset );
  470.     Part1->Size = Offset;
  471.     memmove( Part1->Address, This->Address, Part1->Size );
  472.  
  473.     Part2->Address = MemRealloc( Part2->Address, This->Size - Offset );
  474.     Part2->Size = This->Size - Offset;
  475.     memmove( Part2->Address, ((char *)This->Address) + Offset, Part2->Size );
  476. }
  477.  
  478. static VBCompareFunction StaticUserCompare;
  479.  
  480. static int Compare( const void * VB1, const void * VB2 )
  481. {
  482.     return StaticUserCompare( *(VarBuf *)VB1, *(VarBuf *)VB2 );
  483. }
  484.  
  485. void VBSortArrayOfVB(
  486.     VarBuf Array,
  487.     VBCompareFunction UserCompare )
  488. {
  489.     StaticUserCompare = UserCompare;
  490.  
  491.     qsort( Array->Address, Array->Size / sizeof (VarBuf),
  492.            sizeof (VarBuf), Compare );
  493. }
  494.  
  495. void VBAppendBytes( VarBuf Array, void * Bytes, size_t size )
  496. {
  497.     Array->Address = MemRealloc( Array->Address, Array->Size + size );
  498.  
  499.     memmove( ((char *)Array->Address) + Array->Size, Bytes, size );
  500.  
  501.     Array->Size += size;
  502. }
  503.  
  504. void VBAppendVBReference( VarBuf Array, VarBuf Element )
  505. {
  506.     VBAppendBytes( Array, &Element, sizeof(VarBuf) );
  507. }
  508.  
  509. void VBAppendVoidPtr( VarBuf Array, void * Element )
  510. {
  511.     VBAppendBytes( Array, &Element, sizeof(void *) );
  512. }
  513.  
  514.  
  515. Natural VBNumberOfLines( VarBuf This )
  516. {
  517.     size_t i;
  518.     Natural NumberOfLines = 0;
  519.  
  520.     for ( i = 0; i < This->Size; i++ )
  521.     {
  522.     if ( ((char *)This->Address)[i] == '\n' )
  523.     {
  524.         NumberOfLines++;
  525.     }
  526.     }
  527.  
  528.     return NumberOfLines;
  529. }
  530.  
  531.  
  532. void VBEndWithNewline( VarBuf This )
  533. {
  534.     if ( This->Size > 0 )
  535.     {
  536.     if ( ((char *)This->Address)[This->Size - 1] != '\n' )
  537.     {
  538.         VBAppendCharacter( This, '\n' );
  539.     }
  540.     }
  541. }
  542.  
  543.  
  544. VarBuf VBCreateString( const char * InitialString )
  545. {
  546.     VarBuf New = VBCreate();
  547.  
  548.     VBAppendString( New, InitialString );
  549.  
  550.     return New;
  551. }
  552.